home *** CD-ROM | disk | FTP | other *** search
- /*********************************************************************\
- ** ________________________________ **
- ** A n t h o n y |________ __ __ ________| **
- ** | |o_| |o_| | **
- ** T h y s s e n __| __ __ |__ **
- ** __| __| | | |__ |__ **
- ** `` Dragon Computing ! '' __| __| | | |__ |__ **
- ** |_____| |__| |_____| **
- ** **
- \*********************************************************************/
- /* This file has routines to allow us to 'monitor' an Intuition port
- **
- ** What happens, is that we create a port, `OurPort', and set things
- ** up so that GetMsg() works normally for OurPort, and the original
- ** port, WBPort. However, PutMsg() to OurPort will put the new message
- ** on WBPort, and vice-versa. Basically, the heads of both message
- ** lists are normal, but the two tails have been swapped. Since
- ** GetMsg() uses the head of the list, it acts normally. PutMsg() uses
- ** the tail of the list, so it acts differently. (the sigBit and
- ** sigTasks have also been swapped)
- **
- ** What this means, is that anything PutMsg()'ed to the WBPort (an
- ** intuiMessage for the Workbench), will signal us, and we can then
- ** GetMsg() it. When we are finished looking at that message, we can
- ** give it to WBPort by a PutMsg() to OurPort.
- */
-
- #include "AMenu.h"
-
- extern struct MsgPort *WBReplyPort;
- extern int WBMenus, WBProcesses;
- extern BOOL AddMenuStrip();
- extern void DelMenuStrip(), WBFree(), RunItem();
-
- static struct MsgPort *WBPort;
- static struct List *WBMsgList;
- static LONG WBSignal, OurSignal;
- static BYTE OrigPri;
-
-
- /* our port */
- static struct MsgPort OurPort = {
- {NULL, NULL, NT_MSGPORT, 0, NULL},
- PA_SIGNAL, 0, NULL,
- {NULL, NULL, NULL, NT_MESSAGE, 0}
- };
-
- static struct List *OurMsgList = &(OurPort.mp_MsgList);
-
- /*-----------------------------------------------------*/
-
- void
- AttachMsgPort()
- /* fiddle with the two ports, setting things up */
- {
- Forbid();
-
- /* get the info we need */
- WBPort = M->WBWindow->UserPort;
- WBMsgList = &(WBPort->mp_MsgList);
- WBSignal = WBPort->mp_SigBit;
-
- /* setup our port */
- OurPort.mp_SigBit = WBSignal;
- OurPort.mp_SigTask = WBPort->mp_SigTask;
-
- /* flip things around */
- WBPort->mp_SigTask = M->Handler;
- OurMsgList->lh_Head = (struct Node *)&(WBMsgList->lh_Tail);
- OurMsgList->lh_TailPred = WBMsgList->lh_TailPred;
- WBMsgList->lh_TailPred = (struct Node *)&(OurMsgList->lh_Head);
- OurMsgList->lh_TailPred->ln_Succ = (struct Node *)&(OurMsgList->lh_Tail);
-
- Permit();
-
- /* prevent deadlocks - adjust our Prioity above that of Workbench */
- OrigPri = SetTaskPri(M->Handler, OurPort.mp_SigTask->tc_Node.ln_Pri+1);
- }
-
-
- void
- DeleteMsgPort()
- /* Restore things the way they were before make_MsgPort()
- ** Note that we don't refer to winPort. This is because we
- ** may have had someone else 'monitor' this port (such as MonIDCMP)
- ** besides us, since we attached to it.
- */
- {
- register struct Message *TmpMsg;
- register struct MsgPort *TmpPort;
-
- Forbid();
- /* clean out our list */
- while ((TmpMsg = GetMsg(&OurPort)) != NULL) PutMsg(&OurPort, TmpMsg);
-
- /* find MsgPort that OurMsgList->lh_Head belongs to */
- /* (the port we've been PutMsg'ing to) */
- TmpPort = (struct MsgPort *) (
- (UBYTE*) &OurPort - (UBYTE*) &(OurPort.mp_MsgList.lh_Tail)
- + (UBYTE*)OurMsgList->lh_Head);
-
- /* restore things */
- OurMsgList->lh_Head->ln_Pred = OurMsgList->lh_TailPred;
- OurMsgList->lh_TailPred->ln_Succ = OurMsgList->lh_Head;
- TmpPort->mp_SigTask = OurPort.mp_SigTask;
- Permit();
-
- SetTaskPri(M->Handler, OrigPri); /* return prioity to normal */
- }
-
-
- void
- FinishMonitor()
- /* clean up everything */
- {
- DeleteMsgPort();
- FreeSignal(OurSignal);
- }
-
-
- BOOL
- StartMonitor()
- /* do all appropriate initialization of monitor */
- {
- AttachMsgPort();
- /* we need to allocate the same signal, so that it doesn't get
- allocated to something else, messing us up */
- OurSignal = AllocSignal(WBSignal);
- if (OurSignal != WBSignal) {
- FinishMonitor();
- return FALSE;
- }
- return TRUE;
- }
-
-
- /* Check if Menu code is from our menu items */
- struct ExtMenuItem *
- MatchItem(Code)
- USHORT Code;
- {
- if( MENUNUM( Code ) < WBMenus )
- return NULL; /* a workbench menu */
- return (struct ExtMenuItem *) ItemAddress(M->WBWindow->MenuStrip, Code);
- }
-
-
- /* The actual monitor. Just keep waiting for messages, and acting on them
- * Note that if we don't use a certain IDCMP message, we PutMsg it to get
- * it back to the window it was meant for.
- */
- #define CtrlC SIGBREAKF_CTRL_C /* Exit Signal */
- #define CtrlD SIGBREAKF_CTRL_D /* Update Signal */
- #define CtrlMask (CtrlC|CtrlD)
-
- void
- Monitor()
- {
- register struct IntuiMessage *Msg;
- register struct ExtMenuItem *EItem;
- register ULONG RetMask, WaitMask, WBReplyMask;
-
- WBReplyMask = 1L << WBReplyPort->mp_SigBit;
-
- WaitMask = (1L << WBSignal) | WBReplyMask | CtrlMask;
-
- while( TRUE ) {
- RetMask = Wait(WaitMask);
-
- if( RetMask & CtrlC ) /* ^C - RemoveHandler in progress */
- break;
-
- if( RetMask & CtrlD ) { /* ^D - Update menus */
- DB( FPrintf(DBWindow, "AMenu Update\n"); )
- DelMenuStrip();
- DB( FPrintf(DBWindow, " Signaling Parent ready to update\n"); )
- Signal(M->Parent, (1 << M->ParentSig));
- if( Wait(CtrlMask) & CtrlC )
- break; /* if ^C - RemoveHandler in progress - else continue */
- DB( FPrintf(DBWindow, " Parent Signals Update complete\n"); )
- AddMenuStrip(); /* ignore return - it always does it */
- continue;
- }
-
- if( RetMask & WBReplyMask ) { /* a WB program Replied */
- register struct Message *WBMsg;
- DB( FPrintf(DBWindow, "WB Program Exited -- Freeing Message\n"); )
- while ((WBMsg = GetMsg(WBReplyPort)) != NULL)
- WBFree(WBMsg);
- continue;
- }
- /* Intercepted a WB IDCMP message */
- while( Msg = (struct IntuiMessage *)GetMsg(&OurPort) ) {
- switch( Msg->Class ) {
- case MENUPICK:
- if( EItem = MatchItem(Msg->Code) ) {
- /* Found one of our menu selections */
- ReplyMsg((struct Message *)Msg); /* reply directly */
- DB( FPrintf(DBWindow, "Menu selection `%s'\n",
- ((struct IntuiText *)EItem->MenuItem.ItemFill)->IText); )
- RunItem(EItem); /* run the indicated program */
- } else
- PutMsg(&OurPort, (struct Message *)Msg); /* pass on to WB */
- break;
- case NEWPREFS:
- DB( FPrintf(DBWindow, "NewPrefs recieved - reattaching\n"); )
- PutMsg(&OurPort, (struct Message *)Msg); /* pass on to WB */
- /* loop until menus detached by WB and then we reattach them */
- while( !AddMenuStrip() )
- Delay(30);
- DB( FPrintf(DBWindow, "-- DONE\n"); )
- break;
- default:
- PutMsg(&OurPort, (struct Message *)Msg); /* pass on to WB */
- }
- }
- }
- }
-
-